package com.xbongbong.paas.handle;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.MultiUnitPricePoJo;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ProductCategoryEntity;
import com.xbongbong.saas.enums.ChildProductFieldEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.model.ProductUnitPriceModel;
import com.xbongbong.saas.service.ProductCategoryService;
import com.xbongbong.saas.service.toolbox.help.SaasListDataPermissionHelp;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author lee
 * @version v1.0
 * @date 2020/3/31 16:33
 * @since v1.0
 */
@Component
public class ProductAnalysisDataHandle extends AbstractWebDataAnalysisHandle {

    private final static Logger LOGGER = LoggerFactory.getLogger(ProductAnalysisDataHandle.class);

    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private SaasListDataPermissionHelp saasListDataPermissionHelp;
    @Resource
    private ProductCategoryService productCategoryService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ProductUnitPriceModel productUnitPriceModel;

    @Override
    public PaasFormDataEsListVO analysisData(FormDataListDTO formDataListDTO) throws XbbException {
        PaasFormDataEsListVO formDataListVO;
        try {
            //产品列表的筛选条件会作用到父产品或子产品或两者上
            //筛选条件来源：模糊搜索、常用筛选、分组
            String corpid = formDataListDTO.getCorpid();
            UserEntity userEntity = new UserEntity();
            BeanUtil.copyProperties(formDataListDTO.getLoginUser(),userEntity);
            List<ConditionsEntityExt> conditionList = formDataListDTO.getConditions();
            List<List<ConditionsEntityExt>> shouldConditionList = formDataListDTO.getShouldConditions();
            saasListHelp.packageGroupList(formDataListDTO,conditionList,shouldConditionList);
            List<ConditionsEntityExt> childConditionList = new ArrayList<>();
            Iterator<ConditionsEntityExt> iterator = conditionList.iterator();
            while (iterator.hasNext()){
                ConditionsEntityExt conditionsEntityExt = iterator.next();
                String attr = conditionsEntityExt.getAttr();
                if (Objects.equals(attr, ProductEnum.CATEGORY_ID.getAttr())){
                    Long categoryId = Long.valueOf(conditionsEntityExt.getValue().get(0).toString());
                    List<ProductCategoryEntity> productCategoryList = productCategoryService.getSubCategoryIdList(corpid, categoryId);
                    if (Objects.isNull(productCategoryList)) {
                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205049, ProductErrorCodeEnum.API_ERROR_205049.getMsg());
                    }
                    List<Long> productCategoryIdIn = new ArrayList<>();
                    productCategoryList.forEach(item->productCategoryIdIn.add(item.getId()));
                    if (!productCategoryIdIn.isEmpty()) {
                        List<Object> categoryIdIn = new ArrayList<>(productCategoryIdIn);
                        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
                        conditionsEntityExt.setValue(categoryIdIn);
                    }
                }

                if (Objects.equals(attr, ProductEnum.ENABLE_MULTI_UNIT.getAttr())) {
                    if (Objects.equals(conditionsEntityExt.getValue().get(0), BasicConstant.ZERO)) {
                        conditionsEntityExt.setSymbol(ConditionEnum.NOEQUAL.getSymbol());
                        conditionsEntityExt.setValue(Arrays.asList(BasicConstant.ONE));
                    }
                }

                boolean isChildField = ChildProductFieldEnum.isChildField(attr);
                if (isChildField){
                    //子产品字段
                    if (Objects.equals(attr,ProductEnum.SPECIFICATION.getAttr())){
                        conditionsEntityExt.setAttr(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                    }
                    childConditionList.add(conditionsEntityExt);
                    iterator.remove();
                }
            }

            // 模糊搜索中的规格匹配
            String nameLike = formDataListDTO.getNameLike();
            if (StringUtil.isNotEmpty(nameLike)){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
                boolQueryBuilder.filter(matchPhraseQuery(ProductEnum.getAttrConnectData(ProductEnum.SPECIFICATION_LINK_TEXT),nameLike));
                boolQueryBuilder.mustNot(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), Collections.singletonList(0)));
                List<String> fieldList = new ArrayList<>();
                fieldList.add(StringConstant.DATA_ID);
                fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
                List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,fieldList);
                Set<Long> parentIdList = new HashSet<>();
                for (PaasFormDataEntityExt entityExt : childProductList){
                    parentIdList.add(entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
                }
                formDataListDTO.setNameLikeIdIn(new ArrayList<>(parentIdList));
            }
            // 规格的常用筛选
            if (!childConditionList.isEmpty()){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
                EsUtil.parseCondition(boolQueryBuilder,childConditionList,"",corpid,XbbRefTypeEnum.PRODUCT.getCode());
                boolQueryBuilder.mustNot(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), Collections.singletonList(0)));
                List<String> childProductFieldList = new ArrayList<>();
                childProductFieldList.add(StringConstant.DATA_ID);
                childProductFieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
                List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,childProductFieldList);
                Set<Long> parentIdList = new HashSet<>();
                parentIdList.add(-1L);
                for (PaasFormDataEntityExt entityExt : childProductList){
                    parentIdList.add(entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
                }
                conditionList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),new ArrayList<>(parentIdList)));
            }

            conditionList.add(new ConditionsEntityExt(ProductEnum.PARENT_ID.getAttr(),"",ProductEnum.PARENT_ID.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(0)));
            //分组提前解析，这里重置
            formDataListDTO.setListGroupId(0L);
            formDataListDTO.setDefaultGroup(1);
            saasListDataPermissionHelp.listDepAndUserDataPermission(shouldConditionList,formDataListDTO.getLoginUser(),XbbRefTypeEnum.PRODUCT.getCode(),formDataListDTO.getLoginUser().getDepSet());
            formDataListVO = getEsList(formDataListDTO);
            if ( Objects.equals(formDataListDTO.getFromExport(), BasicConstant.ONE) || Objects.equals(formDataListDTO.getFromExport(), BasicConstant.TWO)  ) {
                return formDataListVO;
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("CustomerAnalysisDataHandle.analysisData 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return formDataListVO;
    }

    /**
     * 指标穿透时，只查子产品部分
     * @param formDataListDTO
     * @return
     * @throws XbbException
     */
    public PaasFormDataEsListVO analysisDataByIndex(FormDataListDTO formDataListDTO) throws XbbException {
        PaasFormDataEsListVO formDataListVO;
        try {
            //产品列表的筛选条件会作用到父产品或子产品或两者上
            //筛选条件来源：模糊搜索、常用筛选、分组
            String corpid = formDataListDTO.getCorpid();
            UserEntity userEntity = new UserEntity();
            BeanUtil.copyProperties(formDataListDTO.getLoginUser(),userEntity);
            List<ConditionsEntityExt> conditionList = formDataListDTO.getConditions();
            List<List<ConditionsEntityExt>> shouldConditionList = formDataListDTO.getShouldConditions();
            saasListHelp.packageGroupList(formDataListDTO,conditionList,shouldConditionList);
            List<ConditionsEntityExt> childConditionList = new ArrayList<>();
            Iterator<ConditionsEntityExt> iterator = conditionList.iterator();
            while (iterator.hasNext()){
                ConditionsEntityExt conditionsEntityExt = iterator.next();
                String attr = conditionsEntityExt.getAttr();
                if (Objects.equals(attr, ProductEnum.CATEGORY_ID.getAttr())){
                    Long categoryId = Long.valueOf(conditionsEntityExt.getValue().get(0).toString());
                    List<ProductCategoryEntity> productCategoryList = productCategoryService.getSubCategoryIdList(corpid, categoryId);
                    if (Objects.isNull(productCategoryList)) {
                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205049, ProductErrorCodeEnum.API_ERROR_205049.getMsg());
                    }
                    List<Long> productCategoryIdIn = new ArrayList<>();
                    productCategoryList.forEach(item->productCategoryIdIn.add(item.getId()));
                    if (!productCategoryIdIn.isEmpty()) {
                        List<Object> categoryIdIn = new ArrayList<>(productCategoryIdIn);
                        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
                        conditionsEntityExt.setValue(categoryIdIn);
                    }
                }

                boolean isChildField = ChildProductFieldEnum.isChildField(attr);
                if (isChildField){
                    //子产品字段
                    if (Objects.equals(attr,ProductEnum.SPECIFICATION.getAttr())){
                        conditionsEntityExt.setAttr(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                    }
                    childConditionList.add(conditionsEntityExt);
                    iterator.remove();
                }
            }

            // 模糊搜索中的规格匹配
            String nameLike = formDataListDTO.getNameLike();
            if (StringUtil.isNotEmpty(nameLike)){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
                boolQueryBuilder.filter(matchPhraseQuery(ProductEnum.getAttrConnectData(ProductEnum.SPECIFICATION_LINK_TEXT),nameLike));
                boolQueryBuilder.mustNot(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), Collections.singletonList(0)));
                List<String> fieldList = new ArrayList<>();
                fieldList.add(StringConstant.DATA_ID);
                fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
                List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,fieldList);
                Set<Long> parentIdList = new HashSet<>();
                for (PaasFormDataEntityExt entityExt : childProductList){
                    parentIdList.add(entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
                }
                formDataListDTO.setNameLikeIdIn(new ArrayList<>(parentIdList));
            }
            // 规格的常用筛选
            if (!childConditionList.isEmpty()){
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
                EsUtil.parseCondition(boolQueryBuilder,childConditionList,"",corpid,XbbRefTypeEnum.PRODUCT.getCode());
                boolQueryBuilder.mustNot(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), Collections.singletonList(0)));
                List<String> childProductFieldList = new ArrayList<>();
                childProductFieldList.add(StringConstant.DATA_ID);
                childProductFieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
                List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,childProductFieldList);
                Set<Long> parentIdList = new HashSet<>();
                parentIdList.add(-1L);
                for (PaasFormDataEntityExt entityExt : childProductList){
                    parentIdList.add(entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
                }
                conditionList.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(),ConditionEnum.IN.getSymbol(),new ArrayList<>(parentIdList)));
            }

            conditionList.add(new ConditionsEntityExt(ProductEnum.PARENT_ID.getAttr(),"",ProductEnum.PARENT_ID.getFieldType(),ConditionEnum.NOEQUAL.getSymbol(),Collections.singletonList(0)));
            //分组提前解析，这里重置
            formDataListDTO.setListGroupId(0L);
            formDataListDTO.setDefaultGroup(1);
            saasListDataPermissionHelp.listDepAndUserDataPermission(shouldConditionList,formDataListDTO.getLoginUser(),XbbRefTypeEnum.PRODUCT.getCode(),formDataListDTO.getLoginUser().getDepSet());
            formDataListVO = getEsList(formDataListDTO);
            List<PaasFormDataEntityExt> paasFormDataEntityExts = formDataListVO.getPaasFormDataESList();
            Set<Long> multiUnitProductIdIn = new HashSet<>(16);
            paasFormDataEntityExts.forEach(entity->{
                if (Objects.equals(entity.getSourceData().getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), 1)) {
                    multiUnitProductIdIn.add(entity.getDataId());
                }
            });
            Map<Long, List<MultiUnitPricePoJo>> priceMap = productUnitPriceModel.getPriceMapByProductIdSet(corpid, multiUnitProductIdIn);
            //字段重新塞入，部分字段在ProductOptionHandle.getListOption方法内remove，而指标穿透需要展示
            paasFormDataEntityExts.forEach(e -> {
                JSONObject sourceData = e.getSourceData();
                JSONObject data = e.getData();
                List<MultiUnitPricePoJo> multiUnitPricePoJos = priceMap.get(e.getDataId());
                if (Objects.nonNull(multiUnitPricePoJos)) {
                    multiUnitPricePoJos.sort((o1, o2) -> Arith.sub(o1.getRate() == null ? 0D : o1.getRate(), o2.getRate() == null ? 0D : o2.getRate()) > 0 ? 1 : -1);
                    String priceStr = multiUnitPricePoJos.get(0).getRate() + "-" + multiUnitPricePoJos.get(multiUnitPricePoJos.size() - 1).getRate();
                    data.put(ProductEnum.PRICE.getAttr(), priceStr);
                } else {
                    data.put(ProductEnum.PRICE.getAttr(), sourceData.get(ProductEnum.PRICE.getAttr()));
                }

                data.put(ProductEnum.COST.getAttr(), sourceData.get(ProductEnum.COST.getAttr()));
                data.put(ProductEnum.SPECIFICATION.getAttr(), sourceData.get(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                data.put(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), sourceData.get(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                data.put(ProductEnum.SUPPLIER.getAttr(), sourceData.get(ProductEnum.SUPPLIER.getAttr()));
                data.put(ProductEnum.SUPPLIER_LINK_TEXT.getAttr(), sourceData.get(ProductEnum.SUPPLIER_LINK_TEXT.getAttr()));
                data.put(ProductEnum.STOCK.getAttr(), sourceData.get(ProductEnum.STOCK.getAttr()));
            });
            if ( Objects.equals(formDataListDTO.getFromExport(), BasicConstant.ONE) || Objects.equals(formDataListDTO.getFromExport(), BasicConstant.TWO) ) {
                return formDataListVO;
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("CustomerAnalysisDataHandle.analysisData 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return formDataListVO;
    }

}
